// Copyright 2023 Huawei Cloud Computing Technology Co., Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef VIDEO_AGENT_H
#define VIDEO_AGENT_H
#include <mutex>
#include "VideoEngine.h"
#include "Log/logging.h"
#include "OSLib/VmiTimer.h"
#include "EncoderPoolClient/client_common.h"

class VideoAgent {
public:
    static constexpr int VIDEO_AGENT_STATUS_INIT = 0;
    static constexpr int VIDEO_AGENT_STATUS_IDLE = 1;
    static constexpr int VIDEO_AGENT_STATUS_CONNECTED = 2;
    static constexpr int VIDEO_AGENT_EVENT_ACCEPT = 3;
    static constexpr int VIDEO_AGENT_EVENT_BREAK = 4;

    /**
     * @功能描述：处理Agent状态机处理函数
     * @参数 [in] event：取值有VIDEO_AGENT_EVENT_ACCEPT等6种事件
     * @返回值：true,代表状态迁移成功。false,代表状态迁移失败
     */
    bool AgentEventNotice(int event);

    /**
     * @功能描述：VideoAgent的单例函数
     * @返回值：返回VideoAgent单例对象指针
     */
    static VideoAgent* GetInstance();

    /**
     * @功能描述：VideoAgent的析构函数
     */
    ~VideoAgent();

    /**
     * @功能描述：VideoAgent的退出函数。设置退出条件，触发AGENT进程退出。
     */
    void Exit();

    /**
     * @功能描述：初始化消息队列，启动计时器线程和数据发送线程
     * @返回值：true,代表需要重新初始化。false,代表不需要重新初始化
     */
    bool Init(int clientPort, const std::string& encoderType, const std::string& videoFrameType, const std::string& resolution, const std::string& fps);

    /**
     * @功能描述：销毁消息队列，停止计时器线程和数据发送线程
     */
    void DeInit();

    /**
     * @功能描述：Agent事件循环函数
     */
    void AgentMainLoop();

    /**
     * @功能描述：设置当前VideoAgent的状态
     * @参数 [in] status：取值有VIDEO_AGENT_STATUS_IDLE等3种状态
     */
    void SetStatus(int status);

    /**
     * @功能描述：设置当前VideoAgent的状态
     * @参数 [in] status：取值有VIDEO_AGENT_STATUS_IDLE等3种状态
     */
    uint8_t ParametersValidation(uint8_t encoderType, uint8_t videoFrameType, uint32_t width, uint32_t height, uint32_t fps);

    /**
     * @功能描述：获取当前编码类型
     */
    EncodeType GetEncodeType();
private:
    /**
     * @功能描述：VideoAgent的构造函数
     */
    VideoAgent();

    /**
     * @功能描述：启动socket服务器监听客户端链接
     * @返回值：true,代表初始化成功。false,代表初始化失败
     */
    bool StartServer(int port);

    /**
     * @功能描述：处理Agent状态机Idle状态的事件
     * @参数 [in] event：取值有VIDEO_AGENT_EVENT_ACCEPT等6种事件
     * @返回值：true,代表状态迁移成功。false,代表状态迁移失败
     */
    bool HandleStatusIdle(int event);

    /**
     * @功能描述：处理Agent状态机Connected状态的事件
     * @参数 [in] event：取值有VIDEO_AGENT_EVENT_ACCEPT等6种事件
     * @返回值：true,代表状态迁移成功。false,代表状态迁移失败
     */
    bool HandleStatusConnected(int event);

    /**
     * @功能描述：初始化并启动计时器线程
     * @返回值：true,代表计时器启动成功。false,代表计时器启动失败
     */
    bool InitTimerThread();

    /**
     * @功能描述：销毁计时器线程
     */
    void DeinitTimerThread();

    std::mutex m_statusLock{};
    volatile int m_status = VIDEO_AGENT_STATUS_INIT;
    static VideoAgent* g_instance;
    static std::mutex g_instanceLock;
    VmiTimerThread* m_vmiTimerThread = nullptr;

    std::string m_encoderType;
    std::string m_videoFrameType;
    std::string m_resolution;
    std::string m_frameRate;

    class Garbo {
    public:
        /**
         * @功能描述：Garbo析构函数,删除单例g_instance
         */
        ~Garbo();
    };

    static Garbo g_garbo;
};

#endif
